#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/signal.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/device.h>
#include <linux/pci.h>
#include <linux/interrupt.h> 
#include <asm/uaccess.h> 
 
#include <linux/jiffies.h>
#include <linux/semaphore.h>

#include "ioctl_drv_usr.h"


extern unsigned long virt_addr_kern[];
extern unsigned long phys_addr_kern[];

extern void pcie_bar0_set(int offset, unsigned int val);
extern unsigned int pcie_bar0_get(int offset);



#ifdef CHN1_OPEN

/*
图像通道       	分辨率	          存储空间需求（以1MB为最小单位）	               实际分配       idx_blk_4M   < 每通道 4frame 缓存 >
--------------------------------------------------------------------------------------------------------------
1 - TGIR-W/N	1280×1024×16bit@50fps（默认模式）	           3MB	    4MB       0 ~ 3    (4 * 4M)   - chn-1  (fpga-->ft)
	        	640×512×16bit@100fps（微扫模式）	           1MB	
*/
static int chn1_4M_idx = idx_chn1_GIR_WN;
static int chn1_frm_idx = 1;

void kmalloc_dma_rx_start_chn_1(void)
{	
	unsigned int addr_h = 0, addr_l = 0;
	int idx = idx_chn1_GIR_WN;
	
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx]);	

	//
	// 4M / dma_rx
	//
	pcie_bar0_set(DMA_DST_CH1_1_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH1_1_LOW, addr_l);
	
	pcie_bar0_set(DMA_WR_CMD_CH1, 0x01);
	
	printk("64ibt addr(idx_chn1_GIR_WN:%d): h-0x%X,l-0x%X \n", idx, addr_h, addr_l);
	return;
}


void irq_dma_rx_start_chn_1(void)
{
	unsigned long phys_addr = 0; 
	unsigned int offset = 0;
	int frm_size = SIZE_4M;

	offset = (chn1_4M_idx * SIZE_4M) + (chn1_frm_idx * frm_size);
	 
	phys_addr = offset_to_phys_all(offset); 	

	pcie_bar0_set(DMA_DST_CH1_1_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH1_1_LOW,  (unsigned int)(phys_addr));
	
	pcie_bar0_set(DMA_WR_CMD_CH1, 0x01);	
	
	chn1_frm_idx++;
	if (chn1_frm_idx >= BUF_4_FRAME)  // 4M / dma_buf
	{
		chn1_frm_idx = 0;
	}

	return;
}
#endif



#ifdef CHN2_OPEN

/*
图像通道       	分辨率	          存储空间需求（以1MB为最小单位）	               实际分配       idx_blk_4M   < 每通道 4frame 缓存 >
--------------------------------------------------------------------------------------------------------------
2 - TGIR-SW	    640×512×16bit@50fps	                   1MB	    1MB       4        (1 * 4M)   - chn-2
*/
static int chn2_4M_idx = idx_chn2_TGIR_SW;
static int chn2_frm_idx = 1;

void kmalloc_dma_rx_start_chn_2(void)
{	
	unsigned int addr_h = 0, addr_l = 0;
	int idx = chn2_4M_idx;
	
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx]);	

	//
	// 1M / dma_rx
	//
	pcie_bar0_set(DMA_DST_CH2_1_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH2_1_LOW, addr_l);
	
	pcie_bar0_set(DMA_WR_CMD_CH2, 0x01);
	
	printk("64ibt addr(idx_chn2_TGIR_SW:%d): h-0x%X,l-0x%X \n", idx, addr_h, addr_l);
	return;
}

void irq_dma_rx_start_chn_2(void)
{
	unsigned long phys_addr = 0; 	
	unsigned int offset = 0;
	int frm_size = SIZE_1M;

	offset = (chn2_4M_idx * SIZE_4M) + (chn2_frm_idx * frm_size);
	phys_addr = offset_to_phys_all(offset); 	

	pcie_bar0_set(DMA_DST_CH2_1_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH2_1_LOW,	(unsigned int)(phys_addr));
	
	pcie_bar0_set(DMA_WR_CMD_CH2, 0x01);	
	
	chn2_frm_idx++;
	if (chn2_frm_idx >= BUF_4_FRAME)  // 1M / dma_buf
	{
		chn2_frm_idx = 0;
	}

	return;
}
#endif

#ifdef CHN3_OPEN
/*
图像通道       	分辨率	          存储空间需求（以1MB为最小单位）	               实际分配       idx_blk_4M   < 每通道 4frame 缓存 >
--------------------------------------------------------------------------------------------------------------
3 - NVIR	    640×512×16bit@50fps                    1MB	    1MB       5        (1 * 4M)   - chn-3
*/
static int chn3_4M_idx = idx_chn3_NVIR;
static int chn3_frm_idx = 1;

void kmalloc_dma_rx_start_chn_3(void)
{	
	unsigned int addr_h = 0, addr_l = 0;
	int idx = chn3_4M_idx;
	
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx]);	

	//
	// 1M / dma_rx
	//
	pcie_bar0_set(DMA_DST_CH3_1_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH3_1_LOW, addr_l);
	
	pcie_bar0_set(DMA_WR_CMD_CH3, 0x01);
	
	printk("64ibt addr(idx_chn3_NVIR:%d): h-0x%X,l-0x%X \n", idx, addr_h, addr_l);
	return;
}

void irq_dma_rx_start_chn_3(void)
{
	unsigned long phys_addr = 0; 	
	unsigned int offset = 0;
	int frm_size = SIZE_1M;

	offset = (chn3_4M_idx * SIZE_4M) + (chn3_frm_idx * frm_size);
	phys_addr = offset_to_phys_all(offset); 	

	pcie_bar0_set(DMA_DST_CH3_1_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH3_1_LOW,	(unsigned int)(phys_addr));
	
	pcie_bar0_set(DMA_WR_CMD_CH3, 0x01);	
	
	chn3_frm_idx++;
	if (chn3_frm_idx >= BUF_4_FRAME)  // 1M / dma_buf
	{
		chn3_frm_idx = 0;
	}

	return;
}
#endif

#ifdef CHN4_OPEN
/*
图像通道       	分辨率	          存储空间需求（以1MB为最小单位）	               实际分配       idx_blk_4M   < 每通道 4frame 缓存 >
--------------------------------------------------------------------------------------------------------------
4 - SWIR	    640×512×16bit@50fps	                   1MB	    1MB       6        (1 * 4M)   - chn-4
*/
static int chn4_4M_idx = idx_chn4_SWIR;
static int chn4_frm_idx = 1;

void kmalloc_dma_rx_start_chn_4(void)
{	
	unsigned int addr_h = 0, addr_l = 0;
	int idx = chn4_4M_idx;
	
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx]);	

	//
	// 1M / dma_rx
	//
	pcie_bar0_set(DMA_DST_CH4_1_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH4_1_LOW, addr_l);
	
	pcie_bar0_set(DMA_WR_CMD_CH4, 0x01);
	
	printk("64ibt addr(idx_chn4_SWIR:%d): h-0x%X,l-0x%X \n", idx, addr_h, addr_l);
	return;
}

void irq_dma_rx_start_chn_4(void)
{
	unsigned long phys_addr = 0; 	
	unsigned int offset = 0;
	int frm_size = SIZE_1M;

	offset = (chn4_4M_idx * SIZE_4M) + (chn4_frm_idx * frm_size);
	phys_addr = offset_to_phys_all(offset); 	

	pcie_bar0_set(DMA_DST_CH4_1_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH4_1_LOW,	(unsigned int)(phys_addr));
	
	pcie_bar0_set(DMA_WR_CMD_CH4, 0x01);	
	
	chn4_frm_idx++;
	if (chn4_frm_idx >= BUF_4_FRAME)  // 1M / dma_buf
	{
		chn4_frm_idx = 0;
	}

	return;
}
#endif


#ifdef CHN5_OPEN
/*
图像通道       	分辨率	          存储空间需求（以1MB为最小单位）	               实际分配       idx_blk_4M   < 每通道 4frame 缓存 >
--------------------------------------------------------------------------------------------------------------
5 - TV-SW	    1280×1024×8bit@50fps（跟瞄模式）	           2MB	    8MB       8 ~ 15   (8 * 4M)   - chn-5
	        	2448×2048×8bit@25fps（侦查模式，备用）	5MB	
*/
static int chn5_4M_idx = idx_chn5_TV_SW;
static int chn5_frm_idx = 1;

void kmalloc_dma_rx_start_chn_5(void)
{	
	unsigned int addr_h = 0, addr_l = 0;
	int idx = chn5_4M_idx;
	
	//
	// 8M / dma_rx
	//
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx]);	
	pcie_bar0_set(DMA_DST_CH5_1_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH5_1_LOW, addr_l);
	
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx+1] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx+1]);	
	pcie_bar0_set(DMA_DST_CH5_2_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH5_2_LOW, addr_l);
	
	pcie_bar0_set(DMA_WR_CMD_CH5, 0x01);
	
	printk("64ibt addr(idx_chn5_TV_SW:%d): h-0x%X,l-0x%X \n", idx, addr_h, addr_l);
	return;
}

void irq_dma_rx_start_chn_5(void)
{
	unsigned long phys_addr = 0; 	
	unsigned int offset = 0;
	int frm_size = SIZE_8M;

	offset = (chn5_4M_idx * SIZE_4M) + (chn5_frm_idx * frm_size);
	phys_addr = offset_to_phys_all(offset); 
	pcie_bar0_set(DMA_DST_CH5_1_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH5_1_LOW,  (unsigned int)(phys_addr));
	
	offset += SIZE_4M;
	phys_addr = offset_to_phys_all(offset); 	
	pcie_bar0_set(DMA_DST_CH5_2_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH5_2_LOW,  (unsigned int)(phys_addr));
	
	pcie_bar0_set(DMA_WR_CMD_CH5, 0x01);	
	
	chn5_frm_idx++;
	if (chn5_frm_idx >= BUF_4_FRAME)  // 8M / dma_buf
	{
		chn5_frm_idx = 0;
	}

	return;
}
#endif

#ifdef CHN6_OPEN
/*
图像通道       	分辨率	          存储空间需求（以1MB为最小单位）	               实际分配       idx_blk_4M   < 每通道 4frame 缓存 >
--------------------------------------------------------------------------------------------------------------
6 - TV-W	    1280×1024×8bit@50fps（跟瞄模式）	           2MB	    8MB       16 ~ 23   (8 * 4M)   - chn-6
	        	2448×2048×8bit@25fps（侦查模式，备用）	5MB	
*/
static int chn6_4M_idx = idx_chn6_TV_W;
static int chn6_frm_idx = 1;

void kmalloc_dma_rx_start_chn_6(void)
{	
	unsigned int addr_h = 0, addr_l = 0;
	int idx = chn6_4M_idx;
	
	//
	// 8M / dma_rx
	//
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx]);	
	pcie_bar0_set(DMA_DST_CH6_1_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH6_1_LOW, addr_l);
	
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx+1] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx+1]);	
	pcie_bar0_set(DMA_DST_CH6_2_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH6_2_LOW, addr_l);
	
	pcie_bar0_set(DMA_WR_CMD_CH6, 0x01);
	
	printk("64ibt addr(idx_chn6_TV_W:%d): h-0x%X,l-0x%X \n", idx, addr_h, addr_l);
	return;
}

void irq_dma_rx_start_chn_6(void)
{
	unsigned long phys_addr = 0; 	
	unsigned int offset = 0;
	int frm_size = SIZE_8M;

	offset = (chn6_4M_idx * SIZE_4M) + (chn6_frm_idx * frm_size);
	phys_addr = offset_to_phys_all(offset); 	

	pcie_bar0_set(DMA_DST_CH6_1_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH6_1_LOW,  (unsigned int)(phys_addr));
	
	offset += SIZE_4M;
	phys_addr = offset_to_phys_all(offset); 	
	pcie_bar0_set(DMA_DST_CH6_2_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH6_2_LOW,  (unsigned int)(phys_addr));
	
	pcie_bar0_set(DMA_WR_CMD_CH5, 0x01);	
	
	chn6_frm_idx++;
	if (chn6_frm_idx >= BUF_4_FRAME)  // 8M / dma_buf
	{
		chn6_frm_idx = 0;
	}

	return;
}
#endif


#ifdef CHN7_OPEN
/*
图像通道       	分辨率	          存储空间需求（以1MB为最小单位）	               实际分配       idx_blk_4M   < 每通道 4frame 缓存 >
--------------------------------------------------------------------------------------------------------------
7 - TV-N	    1280×1024×8bit@50fps（跟瞄模式）	           2MB	    16MB      24 ~ 39   (16 * 4M)   - chn-7
	        	4096×3000×8bit@10fps（侦查模式）             12MB	
*/
static int chn7_4M_idx = idx_chn7_TV_N;
static int chn7_frm_idx = 1;

void kmalloc_dma_rx_start_chn_7(void)
{	
	unsigned int addr_h = 0, addr_l = 0;
	int idx = chn7_4M_idx;
	
	//
	// 16M / dma_rx
	//
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx]);	
	pcie_bar0_set(DMA_DST_CH7_1_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH7_1_LOW, addr_l);
	
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx+1] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx+1]);	
	pcie_bar0_set(DMA_DST_CH7_2_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH7_2_LOW, addr_l);
	
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx+2] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx+2]);	
	pcie_bar0_set(DMA_DST_CH7_3_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH7_3_LOW, addr_l);
	
	addr_h = (unsigned int)((unsigned long)phys_addr_kern[idx+3] >> 32);
	addr_l = (unsigned int)((unsigned long)phys_addr_kern[idx+3]);	
	pcie_bar0_set(DMA_DST_CH7_4_HIGH, addr_h);
	pcie_bar0_set(DMA_DST_CH7_4_LOW, addr_l);
	
	pcie_bar0_set(DMA_WR_CMD_CH7, 0x01);
	
	printk("64ibt addr(idx_chn7_TV_N:%d): h-0x%X,l-0x%X \n", idx, addr_h, addr_l);
	return;
}

void irq_dma_rx_start_chn_7(void)
{
	unsigned long phys_addr = 0; 	
	unsigned int offset = 0;
	int frm_size = SIZE_16M;

	offset = (chn7_4M_idx * SIZE_4M) + (chn7_frm_idx * frm_size);
	phys_addr = offset_to_phys_all(offset); 
	pcie_bar0_set(DMA_DST_CH7_1_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH7_1_LOW,  (unsigned int)(phys_addr));
	
	offset += SIZE_4M;
	phys_addr = offset_to_phys_all(offset); 	
	pcie_bar0_set(DMA_DST_CH7_2_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH7_2_LOW,  (unsigned int)(phys_addr));
	
	offset += SIZE_4M;
	phys_addr = offset_to_phys_all(offset); 	
	pcie_bar0_set(DMA_DST_CH7_3_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH7_3_LOW,  (unsigned int)(phys_addr));
	
	offset += SIZE_4M;
	phys_addr = offset_to_phys_all(offset); 	
	pcie_bar0_set(DMA_DST_CH7_4_HIGH, (unsigned int)(phys_addr >> 32));
	pcie_bar0_set(DMA_DST_CH7_4_LOW,  (unsigned int)(phys_addr));
	
	pcie_bar0_set(DMA_WR_CMD_CH5, 0x01);	
	
	chn7_frm_idx++;
	if (chn7_frm_idx >= BUF_4_FRAME)  // 16M / dma_buf
	{
		chn7_frm_idx = 0;
	}

	return;
}
#endif


